﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "MoveLevelShapeHandleAction.h"
#include "IUiDocument.h"
#include "IUiView.h"
#include "GbmpDefaultPickFilterForLocalSnap.h"
#include "GbmpDefaultPickFilterForRemoteSnap.h"
#include "ISnapContext.h"
#include "IModelView.h"
#include "IElementShapeHandle.h"
#include "UiSnapUtils.h"
#include "AlgorithmProject.h"
#include "IUserTransaction.h"
#include "ISnapCandidates.h"
#include "ISnap.h"
#include "Snapper.h"
#include "IGenericElement.h"
#include "IRegenerator.h"
#include "ILevel.h"
#include "ISnapRender.h"
#include "IDocument.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace ggp;

MoveLevelShapeHandleAction::MoveLevelShapeHandleAction(const ElementId& id)
    : m_ShapeHandleId(id)
{
}

MoveLevelShapeHandleAction::~MoveLevelShapeHandleAction()
{

}

bool MoveLevelShapeHandleAction::OnLButtonUp(IUiView* pCurrentView, const gcmp::Vector3d& pos)
{
    if (m_upUserTransaction!=nullptr && m_upUserTransaction->IsStarted())
    {
        m_upUserTransaction->Commit();
    }

    CleanupTempGraphicsShape();
    ISnapRender::Get()->ClearSnapRenderData();
    MarkFinishStatus(ActionFinishStatus::Successful);
    return true;
}

bool MoveLevelShapeHandleAction::OnMovePoint(IUiView* pCurrentView,const gcmp::Vector3d& pos)
{
    gcmp::IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView不能为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IPlane> opPlane = pModelView->GetWorkPlane();
    Vector3d finalPt;
    Vector2d uvParameter;
    AlgorithmProject::Project(pos, opPlane.get(), uvParameter, finalPt);

    IDocument* pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    if (m_upUserTransaction == nullptr)
    {
        m_upUserTransaction = IUserTransaction::Create( pDoc, GBMP_TR(L"修改标高"), false);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_upUserTransaction, L"m_upUserTransaction为空",L"GDMPLab",L"2024-03-30");
    }
    if (m_upUserTransaction->IsStarted())
    {
        m_upUserTransaction->Rollback();

        IElementShapeHandle* pShapeHandle = quick_cast<IElementShapeHandle>(pDoc->GetElement(m_ShapeHandleId));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pShapeHandle != nullptr, L"没获取辅助点",L"GDMPLab",L"2024-03-30");
        //临时对象一般是跟着一般对象走的，当一般对象Rollback时，更新临时对象
        std::vector<ElementId> elementIds(1, pShapeHandle->GetElementId());
        pDoc->GetRegenerator()->ForceRegeneratingElements(elementIds);
    }

    // Rollback后需要重新获取
    // 获取标高及其辅助点
    IElementShapeHandle* pShapeHandle = quick_cast<IElementShapeHandle>(pDoc->GetElement(m_ShapeHandleId));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pShapeHandle != nullptr, L"没获取辅助点",L"GDMPLab",L"2024-03-30");

    IGenericElement* pGenericElement = quick_cast<IGenericElement>(pDoc->GetElement(pShapeHandle->GetMasterId()));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pGenericElement, L"没获取辅助点对应的Element",L"GDMPLab",L"2024-03-30");

    ILevel* pLevel = quick_cast<ILevel>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLevel, L"没获取标高",L"GDMPLab",L"2024-03-30");

    m_upUserTransaction->Start();

    //开始修改标高
    {
        OwnerPtr<ISnapContext> pSnapContext = ISnapContext::Create();
        gcmp::UiSnapUtils::InitSnapContextFromUiView(pSnapContext.get(), pCurrentView, PickPointExchangeData::SnapPlaneType::WorkPlane);

        pSnapContext->SetInputPoint(pos);
        std::vector<ElementId> movingElements;
        movingElements.emplace_back(m_ShapeHandleId);
        if(!m_oFilterForLocalSnap)
        {
            m_oFilterForLocalSnap = NEW_AS_OWNER_PTR(GbmpDefaultPickFilterForLocalSnap, pDoc, movingElements);
        }
        pSnapContext->SetFilterForLocalSnap(m_oFilterForLocalSnap.get());
        if (!m_oFilterForRemoteSnap)
        {
            m_oFilterForRemoteSnap = NEW_AS_OWNER_PTR(GbmpDefaultPickFilterForRemoteSnap, pDoc, movingElements);
        }
        pSnapContext->SetFilterForLocalSnap(m_oFilterForRemoteSnap.get());
        OwnerPtr<ISnapCandidates> candidates = Snapper::Snap(pSnapContext.get());
        const ISnap* pSnap = candidates->GetCurrentSnap();
        if (pSnap)
        {
            finalPt = pSnap->GetSnappedPoint();
        }
        ISnapRender::Get()->Draw(pSnap, SnapTextPositionType::LowerRight);
        Vector3d newPoint(finalPt.X(), finalPt.Y(), pLevel->GetElevation());

        if (!pLevel->MoveAuxiliaryPoint(pModelView, newPoint, m_ShapeHandleId))
        {
            return false;
        }
    }

    pDoc->GetRegenerator()->RegenerateDocument();
    UpdateView();

    return true;
}
